﻿//===================================================================================
// Copyright (c) Ryan Garrett.  All rights reserved.
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE.
//===================================================================================

using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;

namespace Caffeine.Core.Validation
{
    internal sealed class StringValidationRule : ValidationRule<String>
    {
        #region State

        private readonly Boolean _trimWhiteSpace;
        private readonly Int32 _minLength;
        private readonly Int32 _maxLength;
        private readonly String _regularExpression;
        private readonly String _minLengthErrorFormatString;
        private readonly String _maxLengthErrorFormatString;
        private readonly String _regularExpressionErrorString;

        #endregion

        #region Constructors

        public StringValidationRule
        (
            Boolean nonDefaultValueRequired,
            Boolean ignoreCommitted,
            Boolean trimWhiteSpace,
            Int32 minLength,
            Int32 maxLength,
            String valueRequiredMessage,
            String regularExpression,
            String minLengthErrorFormatString,
            String maxLengthErrorFormatString,
            String regularExpressionErrorString
        )   : base(nonDefaultValueRequired, valueRequiredMessage, ignoreCommitted)
        {
            _trimWhiteSpace = trimWhiteSpace;
            _minLength = minLength;
            _maxLength = maxLength;
            _regularExpression = regularExpression;
            _minLengthErrorFormatString = String.IsNullOrEmpty(minLengthErrorFormatString) ? "Must be at least {0} character(s)" : minLengthErrorFormatString;
            _maxLengthErrorFormatString = String.IsNullOrEmpty(maxLengthErrorFormatString) ? "Cannot have more than {0} character(s)" : maxLengthErrorFormatString;
            _regularExpressionErrorString = regularExpressionErrorString;
        }

        #endregion

        #region Public

        public Boolean TrimWhiteSpace
        {
            get
            {
                return _trimWhiteSpace;
            }
        }

        public Int32 MinLength
        {
            get
            {
                return _minLength;
            }
        }

        public Int32 MaxLength
        {
            get
            {
                return _maxLength;
            }
        }

        public String RegularExpression
        {
            get
            {
                return _regularExpression;
            }
        }

        public String MinLengthErrorFormatString
        {
            get
            {
                return _minLengthErrorFormatString;
            }
        }

        public String MaxLengthErrorFormatString
        {
            get
            {
                return _maxLengthErrorFormatString;
            }
        }

        public String RegularExpressionErrorString
        {
            get
            {
                return _regularExpressionErrorString;
            }
        }

        #endregion

        #region Protected

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0")]
        protected override void OnValidate(ModelProperty<String> property, ref IEnumerable<ValidationError> errors, ref Boolean isValid)
        {
            String value = property.Value;
            value = value ?? String.Empty;

            if (TrimWhiteSpace)
            {
                value = value.Trim();
            }

            isValid = true;

            if (value.Length < MinLength)
            {
                isValid = false;
                property.Parent.AddError(ref errors, 0, String.Format(MinLengthErrorFormatString, MinLength));
            }

            if (value.Length > MaxLength)
            {
                isValid = false;
                property.Parent.AddError(ref errors, 0, String.Format(MaxLengthErrorFormatString, MaxLength));
            }

            if (!String.IsNullOrEmpty(RegularExpression))
            {
                if (!Regex.IsMatch(value, RegularExpression, RegexOptions.None))
                {
                    isValid = false;
                    property.Parent.AddError(ref errors, 0, RegularExpressionErrorString);
                }
            }
        }

        #endregion
    }
}
